/**
  ******************************************************************************
  * @file    si2c_sht3x2x.c 
  * @author  make
  * @version V1.0.0
  * @date    2020.10.09
  * @brief   src program body
  ******************************************************************************
  * @attention
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "si2c_comm.h"
#include "tskcfg.h"
#include "bsp.h"

#define SDP810_ADDR_BASE        (0x25u)
#define	SDP810_ADDR_WRITE	      (SDP810_ADDR_BASE<<1)
#define	SDP810_ADDR_READ		    ((SDP810_ADDR_BASE<<1)+1)

#define sdp810_delay(x)         vTaskDelay(x)
#define byte_delay(x)           vTaskDelay(x)

__inline static void sdp810_sda_to_in(void)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	
	GPIO_InitStruct.Pin   = SDP810_SDA_PIN;
	GPIO_InitStruct.Mode  = GPIO_MODE_INPUT;
	GPIO_InitStruct.Pull  = GPIO_PULLUP;
	HAL_GPIO_Init(SDP810_SDA_GPIO_PORT, &GPIO_InitStruct);
}

__inline static void sdp810_sda_to_out(void)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	
	GPIO_InitStruct.Pin   = SDP810_SDA_PIN;
	GPIO_InitStruct.Mode  = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
	GPIO_InitStruct.Pull  = GPIO_PULLUP;
	HAL_GPIO_Init(SDP810_SDA_GPIO_PORT, &GPIO_InitStruct);
}

__inline static void si2c_delay(void)
{
//  uint16_t delay_time=10;
	    
//	while(delay_time--); /*7 400khz , 8 370khz*/
	
	sdp810_delay(2);
}

__inline static void sdp810_si2c_start(void)
{
  sdp810_sda_h();
	sdp810_scl_h();
  si2c_delay();
  
	sdp810_sda_l();      /* sda一个下降沿 */
  si2c_delay();
	
	sdp810_scl_l();
  si2c_delay();
}

__inline static void sdp810_si2c_stop(void)
{
	sdp810_sda_l();
	sdp810_scl_h();
	si2c_delay();
	
	sdp810_sda_h();      /* sda一个上升沿 */
  si2c_delay();
}

__inline static uint8_t sdp810_si2c_write_byte(uint8_t dat)  /* 18 */
{
	uint8_t i, ack;
	
	sdp810_scl_l();                   /* 保证scl处于低 */
	
	for(i=0; i<8; i++)
	{
		if(0x80 & dat)
		{
			sdp810_sda_h();
		}
		else
		{
			sdp810_sda_l();
		}
		
		dat <<= 1;
		
		sdp810_scl_h();                 /* scl拉高 锁存数据 */
    si2c_delay();
		
		sdp810_scl_l();                 /* scl拉低 准备数据 */
    si2c_delay();
	}

  sdp810_sda_to_in();               /*释放data*/
  
  sdp810_scl_h();                   /*第9个时钟的上升沿*/
	si2c_delay();
	
  if(sdp810_scl_r() != 0)
	{
		ack = SI2C_NACK;
	}
	else
	{
		ack = SI2C_ACK;
	}
	
  sdp810_scl_l();                   /*第9个时钟的下降沿*/
	sdp810_sda_to_out();              /*重新控制总线*/
//  si2c_delay();
	
	byte_delay(5);
	
  return ack;
}

__inline static uint8_t sdp810_si2c_read_byte(uint8_t ack)
{
	uint8_t i;
	uint8_t dat;
	
	dat = 0;
	
	sdp810_scl_l();             /* 保证scl处于低 */
	
	sdp810_sda_to_in();
	
	for(i=0; i<8; i++)
	{
		sdp810_scl_h();                  /* scl拉高后,读出数据 */
    si2c_delay();
		
		dat <<= 1;
		
		if(sdp810_scl_r() != 0)
		{
			dat |= 0x01;
		}
		else
		{
			dat &= 0xfe;
		}
		
		sdp810_scl_l();                  /* scl拉低,待对方准备数据 */
    si2c_delay();
	}
	
	sdp810_sda_to_out();
	
	if(ack != SI2C_ACK)
	{
		sdp810_sda_h();  /* SI2C_NACK */
	}
	else
	{
		sdp810_sda_l();  /* SI2C_ACK */
	}
	
  sdp810_scl_h();
  si2c_delay();             /*发送ack*/
	
  sdp810_scl_l();
//  si2c_delay();
	
	byte_delay(5);
	return dat;
}

static uint8_t si2c_send_cmd(uint8_t addr, uint16_t cmd)
{
	sdp810_si2c_start();
	
	if(sdp810_si2c_write_byte(addr) != SI2C_ACK)
	{
		sdp810_si2c_stop();
		return 1;
	}
	
	if(sdp810_si2c_write_byte((uint8_t)(cmd>>8)) != SI2C_ACK)
	{
		sdp810_si2c_stop();
		return 2;
	}
	
	if(sdp810_si2c_write_byte((uint8_t)cmd) != SI2C_ACK)
	{
		sdp810_si2c_stop();
		return 3;
	}
	
	sdp810_si2c_stop();
	
	return 0;
}

void Sdp810_ResetCmd(void)
{
  sdp810_si2c_start();
  
  sdp810_si2c_write_byte(0x00u);
  
  sdp810_si2c_write_byte(0x06u);
	
	sdp810_si2c_stop();
  
  vTaskDelay(10);
}

uint8_t Sdp810_ReInit(void)
{
  uint8_t err;
  
	err = si2c_send_cmd(SDP810_ADDR_WRITE, 0x3608u);
	if(err != 0)
	{
		return 2;
	}
	
	vTaskDelay(500);
	
	return 0;
}

uint8_t Sdp810_GetSingleMeasure(volatile int16_t *pa)
{
	uint8_t buf[4];
	int16_t va;
  
	sdp810_si2c_start();
		
	if(sdp810_si2c_write_byte(SDP810_ADDR_READ) != SI2C_ACK)
	{
		return 1;
	}
	
	buf[0] = sdp810_si2c_read_byte(SI2C_ACK);
	buf[1] = sdp810_si2c_read_byte(SI2C_ACK);
	buf[2] = sdp810_si2c_read_byte(SI2C_NACK);
	
//	buf[3] = sdp810_si2c_read_byte(SI2C_ACK);
//	buf[4] = sdp810_si2c_read_byte(SI2C_ACK);
//	buf[5] = sdp810_si2c_read_byte(SI2C_ACK);
//	
//	buf[6] = sdp810_si2c_read_byte(SI2C_ACK);
//	buf[7] = sdp810_si2c_read_byte(SI2C_ACK);
//	buf[8] = sdp810_si2c_read_byte(SI2C_NACK);
	
	sdp810_si2c_stop();
	
	if(sensor_crc8(buf, 0xFF) != buf[2])
	{
		return 2;
	}
	
	va = (int16_t)((buf[0]<<8)|buf[1]);
//	vb = (int16_t)((buf[3]<<8)|buf[4]);
	
//	*fac = ((buf[6]<<8)|buf[7]);
	*pa = va / 60;
//	*temp = vb / *fac;
	
	return 0;
}
